--[[
ShortLayout

Author : simonw
From CWDG http://bbs.cwowaddon.com/thread-1193-1-1.html

2008.3.8

]]--

ShortLayout = {}
ShortLayout.Config = {}
ShortLayout.Special = {}
ShortLayout.globalHookTable = {}

function ShortLayout.Init()
	--ShortLayout.UIParent_ManageFramePositions = UIParent_ManageFramePositions
	BINDING_HEADER_ShortLayoutHeader = "ShortLayout By simonw. http://cwowaddon.com"
	BINDING_NAME_ShortLayout1 = "Reload config"
	BINDING_NAME_ShortLayout2 = "Get frame args"

	--UIParent_ManageFramePositions = ShortLayout.NoneFunction
end

function ShortLayout.Load(context)
	if (context and context.Slash_Arg and string.len(context.Slash_Arg) > 10) then
		ShortLayout.LoadItem(context.Slash_Arg)
	else
		ShortLayout.LoadAll()
	end
end

function ShortLayout.LoadAll()
	ShortLayout.Print("ShortLayout loaded. By simonw from CWDG cwowaddon.com")
	ShortLayout.PlayerClass = UnitClass("player")
	ShortLayout.PlayerName = UnitName("player")
	ShortLayout.Resolution = GetCVar("gxResolution")
	ShortLayout.UIScale = tonumber(GetCVar("uiScale"))
	ShortLayout:LoadConfig()
end

function ShortLayout.LoadItem(arg)
	loadstring("local item = "..arg..";ShortLayout:SetFrame(item)")()
	ShortLayout.Print("ShortLayout item loaded: "..arg)
end

function ShortLayout.GetMouseFrame()
	local frame = GetMouseFocus()
	local name = frame:GetName()
	local point, relativeTo, relativePoint, xofs, yofs = ShortLayout:Run(frame, "GetPoint")
	local parent = frame:GetParent()
	if (parent) then
		parent = parent:GetName()
	end

	if (relativeTo) then
		relativeTo = relativeTo:GetName()
	end
	local points = string.format("{point:%s, relativeTo:%s, relativePoint:%s, xofs:%s, yofs:%s}",
	point  or "nil",
	relativeTo  or "nil",
	relativePoint  or "nil",
	xofs  or "nil",
	yofs  or "nil")

	ShortLayout.Print(
		string.format(
		"ShortLayout frame: %s Type:%s ID:%s",
		frame:GetName() or "nil",
		frame:GetObjectType() or "nil",
		frame:GetID() or "nil"
		)
	)

	ShortLayout.Print(
		string.format(
		"Top:%s Bottom:%s Left:%s Right:%s Height:%s Width:%s Center:%s NumPoints:%s Parent:%s Protected:%s Points:%s",
		frame:GetTop() or "nil",
		frame:GetBottom() or "nil",
		frame:GetLeft() or "nil",
		frame:GetRight() or "nil",
		frame:GetHeight() or "nil",
		frame:GetWidth() or "nil",
		frame:GetCenter() or "nil",
		frame:GetNumPoints() or "nil",
		parent or "nil",
		frame:IsProtected() or "nil",
		points)
	)
end

------------------------------------------------------------------------------------------------------------------

function ShortLayout:CanLoad(configItem)
	local checkresolution = function ()
		for _, v in ipairs(configItem.Resolution) do
			if (self.Resolution == v) then
				return true
			end
		end
	end

	local checkuiscale = function ()
		if (configItem.UIScale[1] and configItem.UIScale[2]) then
			if (configItem.UIScale[1] <= self.UIScale and configItem.UIScale[2] >= self.UIScale) then
				return true
			end
		end
	end

	if (
		(configItem.Class and configItem.Class ~= self.PlayerClass) or
		(configItem.Character and configItem.Character ~= self.PlayerName) or
		(configItem.Resolution and not checkresolution()) or
		(configItem.UIScale and not checkuiscale())
	) then
		return false
	else
		return true
	end
end

function ShortLayout:LoadConfig()
	for _, config in ipairs(self.Config) do
		if (self:CanLoad(config)) then
			for _, item in ipairs(config) do
				self:SetFrame(item, config.AutoAdjust)
			end
		end
	end
end

function ShortLayout:GetFrames(framename)
	local frames = {}
	if (string.find(framename, "%[")) then
		local _, _, perfix, range, suffix = string.find(framename, "(%S+)%[(%S*)%](%S*)")

		if (not perfix or not range or range == "") then
			ShortLayout.Print("ShortLayout Wrong Config(frame format error): "..framename)
			return frames
		end

		local _, _, head, foot = string.find(range, "(%d+)-?(%d*)")

		head = tonumber(head)
		foot = tonumber(foot)
		suffix = suffix or ""

		if (head and foot) then
			for i = head, foot do
				table.insert(frames, perfix..i..suffix)
			end
		end
	else
		table.insert(frames, framename)
	end

	return frames
end

function ShortLayout:SetFrame(item, isAutoPoint)
	for _, framename in ipairs(self:GetFrames(item.Frame)) do
		item._framename = framename
		item._isautopoint = isAutoPoint

		if (not self:SetSpecialFrame(item)) then
			self:SetItem(item)
		end
	end
end

function ShortLayout:SetSpecialFrame(item)
	local isSpecial = false

	for func, framenames in pairs(self.Special) do
		for _, framename in ipairs(framenames) do
			framenames._items = framenames._items or {}

			if (string.find(item._framename, framename)) then

				framenames._items[item] = true
				isSpecial = true
				func(item)
				break
			end
		end
	end

	return isSpecial
end

function ShortLayout:SetItem(item)
	local frame = getglobal(item._framename)

	-- or InCombatLockdown()

	if (not frame) then
		ShortLayout.Print("ShortLayout Wrong Config(frame not exist): "..item._framename)
		return
	end

	for k, v in pairs(item) do
		if (k == "Frame" or k == "_framename") then

		elseif(k == "cHide") then
			self:CustomSetHide(frame, item.cHide)
		elseif(k == "cSetMovable") then
			self:CustomSetMovable(frame, item.cSetMovable)
		elseif (k == "SetPoint") then
			self:SetPoint(frame, item.SetPoint, item._isautopoint)
		elseif (k == "Function") then
			self:CustomFunction(frame, item.Function)
		else
			self:DoSetting(frame, k, v)
		end
	end
end

function ShortLayout:CustomSetHide(frame, icHide)
	if (not icHide) then return end

	local objType = frame:GetObjectType()
	if (objType == "Frame" or objType == "Button" or objType == "CheckButton") then
		frame:SetScript("OnShow", function () this:Hide() end)
	end
	frame:SetAlpha(0)
	frame:Hide()
end

function ShortLayout:CustomSetMovable(frame, isMovbale)
	if (not isMovbale) then return end

	frame:SetMovable(true)
	local start = function ()
		if(arg1 == "LeftButton" and IsAltKeyDown() and IsControlKeyDown()) then
			frame:StartMoving()
		end
	end

	local stop = function ()
		if(arg1 == "LeftButton") then
			frame:StopMovingOrSizing()
		end
	end
	frame:SetScript("OnMouseDown", start)
	frame:SetScript("OnMouseUp", stop)
end

function ShortLayout:CustomFunction(frame, func)
	if (func) then
		if (type(func) == "function") then
			func(frame)
		elseif (getglobal(func)) then
			getglobal(func)(frame)
		end
	end
end

function ShortLayout:SetPoint(frame, points, isAuto)
	if (points) then
		frame:ClearAllPoints()
		if (isAuto and points[4] and points[5]) then
			frame:SetPoint(points[1], points[2], points[3], points[4]*ShortLayout.UIScale, points[5]*ShortLayout.UIScale)
		else
			frame:SetPoint(points[1], points[2], points[3], points[4], points[5])
		end
	end
end

function ShortLayout:DoSetting(frame, func, arg)
	if (arg) then
		if (type(arg) == "table" and arg.IsObjectType) then
			self:Run(frame, func, unpack(arg))
		else
			self:Run(frame, func, arg)
		end
	end
end

function ShortLayout:Run(frame, func, ...)
	local run = frame[func]
	if (run) then
		return run(frame, ...)
	else
		ShortLayout.Print(string.format("ShortLayout Wrong Config: %s:%s", frame:GetName(), func))
	end
end

function ShortLayout:SetGlobalHookTable(funcstring)
	if (not self.globalHookTable[funcstring]) then
		self.globalHookTable[funcstring] = getglobal(funcstring)
	end
end

function ShortLayout:GetSpecialHookFunc(item, customFunc, hookFuncString, ...)
	return function (...)
		--local result = self.globalHookTable[hookFuncString](...)

		for specialItem, _ in pairs(self.Special[customFunc]._items) do
			self:SetItem(specialItem)
		end

		--return result
	end
end

function ShortLayout:DefaultCustomFunc(item, customFunc, hookFuncString, ...)
	self:SetGlobalHookTable(hookFuncString)
	self:SetItem(item)
	self._hookfunc = self:GetSpecialHookFunc(item, customFunc, hookFuncString, ...)
	--loadstring(hookFuncString .. " = ShortLayout._hookfunc")()

	hooksecurefunc(hookFuncString, self._hookfunc)
end

function ShortLayout.Print(msg)
	DEFAULT_CHAT_FRAME:AddMessage(msg or "nil")
end

---------------------------- Blocks ----------------------------
ShortLayoutAddon = EVA.Addon:New()
ShortLayoutAddon.Name = "ShortLayout"
ShortLayoutAddon.Version = "1.5"
ShortLayoutAddon.Description = "Layout Frame Based On WOW Default. By simonw. URL[http://cwowaddon.com/]"
EVA.AddonRegistry:Add(ShortLayoutAddon)

local initBlock = {
	Name = "",
	Description = "",
	RequestTypes = {"Event"},
	Events = {"VARIABLES_LOADED"},
	Enabled = true,
	Commands = {
		{Description = "", Function = ShortLayout.Init},
	}
}

local loadBlock = {
	Name = "",
	Description = "",
	RequestTypes = {"Event", "SlashCommand"},
	SlashCommands = {"/shortlayout", "/sl"},
	Events = {"PLAYER_LOGIN"},
	--Events = {"VARIABLES_LOADED"},
	Enabled = true,
	Commands = {
		{Description = "", Function = ShortLayout.Load},
	}
}

ShortLayoutAddon:Add(EVA.Block:New(initBlock))
ShortLayoutAddon:Add(EVA.Block:New(loadBlock))

-- /script ReloadUI()
-- /script ShortLayout.Print(string.find("BuffButton1", "(BuffButton.*)"))
